#include <cstdio>
class SegamentTree
{
    struct node
    {
        long long ad = 0, mu = 1, va = 0;
        node *ch[2] = {NULL, NULL};
    };
    inline int mid(int L, int R)
    {
        return (L + R) >> 1;
    }
    inline void upd(node *now)
    {
        now->va = ((now->ch[0] == NULL ? 0 : now->ch[0]->va) + (now->ch[1] == NULL ? 0 : now->ch[1]->va)) % P;
    }
    inline void ADD(node *now, long long v, int L, int R)
    {
        if (now == NULL)
            return;

        now->va = (now->va + v * (R - L + 1) % P) % P;
        now->ad = (now->ad + v) % P;
    }
    inline void MUL(node *now, long long v)
    {
        if (now == NULL)
            return;

        now->va = (now->va * v) % P;
        now->ad = (now->ad * v) % P;
        now->mu = (now->mu * v) % P;
    }
    inline void down(node *now, int L, int R)
    {
        if (now->mu != 1)
        {
            MUL(now->ch[0], now->mu);
            MUL(now->ch[1], now->mu);
            now->mu = 1;
        }

        if (now->ad)
        {
            ADD(now->ch[0], now->ad, L, mid(L, R));
            ADD(now->ch[1], now->ad, mid(L, R) + 1, R);
            now->ad = 0;
        }
    }
    void _add(int s, int t, long long v, node *&now, int L, int R)
    {
        if (now == NULL)
            now = new node();

        if (s <= L && t >= R)
            ADD(now, v, L, R);

        else
        {
            down(now, L, R);

            if (s <= mid(L, R))
                _add(s, t, v, now->ch[0], L, mid(L, R));

            if (t > mid(L, R))
                _add(s, t, v, now->ch[1], mid(L, R) + 1, R);

            upd(now);
        }
    }
    void _mul(int s, int t, long long v, node *&now, int L, int R)
    {
        if (now == NULL)
            now = new node();

        if (s <= L && t >= R)
            MUL(now, v);

        else
        {
            down(now, L, R);

            if (s <= mid(L, R))
                _mul(s, t, v, now->ch[0], L, mid(L, R));

            if (t > mid(L, R))
                _mul(s, t, v, now->ch[1], mid(L, R) + 1, R);

            upd(now);
        }
    }
    long long _get(int s, int t, node *&now, int L, int R)
    {
        if (now == NULL)
            return 0;

        if (s <= L && t >= R)
            return now->va;

        else
        {
            long long ans = 0;
            down(now, L, R);

            if (s <= mid(L, R))
                ans += _get(s, t, now->ch[0], L, mid(L, R));

            if (t > mid(L, R))
                ans += _get(s, t, now->ch[1], mid(L, R) + 1, R);

            return ans % P;
        }
    }
    void _log(node *now, int L, int R)
    {
        if (now == NULL)
            return;

        printf("%d %d %lld %lld %lld\n", L, R, now->va, now->ad, now->mu);
        _log(now->ch[0], L, mid(L, R));
        _log(now->ch[1], mid(L, R) + 1, R);
    }
    void init(const int *li, node *&now, int L, int R)
    {
        now = new node();

        if (L == R)
            now->va = li[L];

        else
        {
            if (L <= mid(L, R))
                init(li, now->ch[0], L, mid(L, R));

            if (R > mid(L, R))
                init(li, now->ch[1], mid(L, R) + 1, R);

            upd(now);
        }
    }

public:
    int N, P;
    node *root;
    SegamentTree(int totN, int P = 0x7fffffff)
    {
        N = totN;
        this->P = P;
    }
    SegamentTree(int totN, const int *li, int P = 0x7fffffff)
    {
        N = totN;
        this->P = P;
        init(li, root, 1, N);
    }
    void add(int s, int t, long long v)
    {
        _add(s, t, v, root, 1, N);
    }
    void mul(int s, int t, long long v)
    {
        _mul(s, t, v, root, 1, N);
    }
    long long get(int s, int t)
    {
        return _get(s, t, root, 1, N);
    }
    long long operator()(int s, int t)
    {
        return _get(s, t, root, 1, N);
    }
    void log()
    {
        _log(root, 1, N);
    }
};
const int N = 100010;
int li[N];
int main()
{
    int n, m, p;
    scanf("%d %d %d", &n, &m, &p);

    for (int i = 1; i <= n; ++i)
        scanf("%d", li + i);

    SegamentTree tr(n, li, p);
    int op, x, y;
    long long k;

    for (int i = 0; i < m; ++i)
    {
        scanf("%d %d %d", &op, &x, &y);

        if (op == 1)
        {
            scanf("%lld", &k);
            tr.mul(x, y, k);
        }

        else if (op == 2)
        {
            scanf("%lld", &k);
            tr.add(x, y, k);
        }

        else
        {
            printf("%lld\n", tr(x, y));
        }
    }

    return 0;
}